{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "2c5f4c57-062d-47b4-8d30-b7e780fa81a6",
   "metadata": {},
   "source": [
    "有时，我们并不需要在路径操作函数中使用依赖项的返回值。\r\n",
    "\r\n",
    "或者说，有些依赖项不返回值。\r\n",
    "\r\n",
    "但仍要执行或解析该依赖项。\r\n",
    "\r\n",
    "对于这种情况，不必在声明路径操作函数的参数时使用 Depends，而是可以在路径操作装饰器中添加一个由 dependencies 组成的 list。"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "335a97aa-c398-4d48-91ec-15f56a051fdc",
   "metadata": {},
   "source": [
    "路径操作装饰器支持可选参数 ~ dependencies。\r\n",
    "\r\n",
    "该参数的值是由 Depends() 组成的 list："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "cb9af127-6312-45ce-bd0c-afb2104e270e",
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "INFO:     Started server process [13712]\n",
      "INFO:     Waiting for application startup.\n",
      "INFO:     Application startup complete.\n",
      "INFO:     Uvicorn running on http://0.0.0.0:8009 (Press CTRL+C to quit)\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "INFO:     127.0.0.1:65369 - \"GET /items/ HTTP/1.1\" 422 Unprocessable Entity\n",
      "INFO:     127.0.0.1:65370 - \"GET /items/ HTTP/1.1\" 422 Unprocessable Entity\n",
      "INFO:     127.0.0.1:65379 - \"GET /items/ HTTP/1.1\" 200 OK\n",
      "INFO:     127.0.0.1:65393 - \"GET /items/ HTTP/1.1\" 400 Bad Request\n",
      "INFO:     127.0.0.1:65397 - \"GET /items/ HTTP/1.1\" 400 Bad Request\n",
      "INFO:     127.0.0.1:65408 - \"GET /items/ HTTP/1.1\" 400 Bad Request\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "INFO:     Shutting down\n",
      "INFO:     Waiting for application shutdown.\n",
      "INFO:     Application shutdown complete.\n",
      "INFO:     Finished server process [13712]\n"
     ]
    }
   ],
   "source": [
    "import uvicorn\n",
    "from fastapi import Depends, FastAPI, Header, HTTPException\n",
    "app = FastAPI()\n",
    "\n",
    "\n",
    "async def verify_token(x_token: str = Header()):\n",
    "    if x_token != \"fake-super-secret-token\":\n",
    "        raise HTTPException(status_code=400, detail=\"X-Token header invalid\")\n",
    "\n",
    "\n",
    "async def verify_key(x_key: str = Header()):\n",
    "    if x_key != \"fake-super-secret-key\":\n",
    "        raise HTTPException(status_code=400, detail=\"X-Key header invalid\")\n",
    "    return x_key\n",
    "\n",
    "\n",
    "@app.get(\"/items/\", dependencies=[Depends(verify_token), Depends(verify_key)])\n",
    "async def read_items():\n",
    "    return [{\"item\": \"Foo\"}, {\"item\": \"Bar\"}]\n",
    "\n",
    "if __name__ == '__main__':\n",
    "    config = uvicorn.Config(app, host='0.0.0.0', port=8009)\n",
    "    server = uvicorn.Server(config)\n",
    "    await server.serve()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "43fe691a-27c2-4317-b41a-4a8ee27b6d8d",
   "metadata": {},
   "outputs": [],
   "source": [
    "url = 'http://127.0.0.1:8009/items/' \n",
    "headers = {\"x-token\": \"fake-super-secret-token\",\"x-key\": \"fake-super-secret-key\"} \n",
    "res = requests.get(url, headers=headers) \n",
    "res.text\n",
    "\n",
    "# 在另一个ipynb文件中运行代码，会得到 '[{\"item\":\"Foo\"},{\"item\":\"Bar\"}]'"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "55d3076d-dd20-45b3-8095-bf92bdb19c1d",
   "metadata": {},
   "outputs": [],
   "source": [
    "url = 'http://127.0.0.1:8009/items/' \n",
    "headers = {\"x-token\": \"fake-super-secret-token1\",\"x-key\": \"fake-super-secret-key\"} \n",
    "res = requests.get(url, headers=headers) \n",
    "res.text\n",
    "\n",
    "# 在另一个ipynb文件中运行代码，会得到 '{\"detail\":\"X-Token header invalid\"}'"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "6fb0643a-fb4c-46c0-aab3-cab9d7fd9acf",
   "metadata": {},
   "outputs": [],
   "source": [
    "url = 'http://127.0.0.1:8009/items/' \n",
    "headers = {\"x-token\": \"fake-super-secret-token\",\"x-key\": \"fake-super-secret-key1\"} \n",
    "res = requests.get(url, headers=headers) \n",
    "res.text\n",
    "\n",
    "# 在另一个ipynb文件中运行代码，会得到 '{\"detail\":\"X-Key header invalid\"}'"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "2af5d04d-d322-4150-941a-4ce7eb9b1186",
   "metadata": {},
   "source": [
    "路径操作装饰器依赖项（以下简称为“路径装饰器依赖项”）的执行或解析方式和普通依赖项一样，但就算这些依赖项会返回值，它们的值也不会传递给路径操作函数。\n",
    "\n",
    "有些编辑器会检查代码中没使用过的函数参数，并显示错误提示。\r\n",
    "\r\n",
    "在路径操作装饰器中使用 dependencies 参数，可以确保在执行依赖项的同时，避免编辑器显示错误提示。\r\n",
    "\r\n",
    "使用路径装饰器依赖项还可以避免开发新人误会代码中包含无用的未使用参数。"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "3b383696-d85d-4cfe-bcb0-214de157b3c0",
   "metadata": {},
   "source": [
    "触发异常\n",
    "\r\n",
    "路径装饰器依赖项与正常的依赖项一样，可以 raise 异常："
   ]
  },
  {
   "cell_type": "markdown",
   "id": "518c0b57-f0e2-44fe-9605-2d91c2454545",
   "metadata": {},
   "source": [
    "返回值\n",
    "\r\n",
    "无论路径装饰器依赖项是否返回值，路径操作都不会使用这些值。\r\n",
    "\r\n",
    "因此，可以复用在其他位置使用过的、（能返回值的）普通依赖项，即使没有使用这个值，也会执行该。赖项："
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.10.5"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
